package igor.lakienko.ru.generation.quotes.service;

import igor.lakienko.ru.generation.quotes.dto.MessageEventDto;
import igor.lakienko.ru.generation.quotes.dto.PreciousMetalDto;
import igor.lakienko.ru.generation.quotes.entity.PreciousMetalEntity;
import igor.lakienko.ru.generation.quotes.enums.PreciousMetal;
import igor.lakienko.ru.generation.quotes.enums.RecommendationAnalysts;
import igor.lakienko.ru.generation.quotes.enums.TypeSecurities;
import igor.lakienko.ru.generation.quotes.mapper.PreciousMetalMapper;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
class PreciousMetalServiceTest {

    @Mock
    PreciousMetalMapper preciousMetalMapper;

    @InjectMocks
    PreciousMetalService preciousMetalService;

    @BeforeEach
    void setUp() {
        getSizeBatchField();
    }

    @Test
    void whenGetMetal_thenSuccessRandomMetalDto() {
        //given
        PreciousMetalDto preciousMetalDefault = getPreciousMetalDefault();
        given(preciousMetalMapper.preciousMetalEntityToDto(any(PreciousMetalEntity.class)))
                .willReturn(preciousMetalDefault);

        //when
        MessageEventDto metal = preciousMetalService.getMetal();

        //then
        assertThat(metal).isEqualTo(preciousMetalDefault);
    }

    @Test
    void whenGetMetals_thenSuccessRandomMetalDtos() {
        //given
        List<PreciousMetalDto> metalDefault = List.of(getPreciousMetalDefault());
        given(preciousMetalMapper.preciousMetalsEntityToDto(anyList())).willReturn(metalDefault);

        //when
        Collection<PreciousMetalDto> metalDtos = preciousMetalService.getMetals();

        //then
        assertThat(metalDtos).isEqualTo(metalDefault);
    }

    @SneakyThrows
    private void getSizeBatchField() {
        Field quoteSizeBatch = preciousMetalService.getClass().getDeclaredField("metalSizeBatch");
        quoteSizeBatch.setAccessible(true);
        quoteSizeBatch.set(preciousMetalService, 2);
    }

    private PreciousMetalDto getPreciousMetalDefault() {
        return PreciousMetalDto.builder()
                .id(UUID.randomUUID().toString())
                .sentAt(ZonedDateTime.now())
                .type(TypeSecurities.STOCK)
                .preciousMetal(PreciousMetal.FXGLC1)
                .bidVolume(20)
                .offerVolume(50)
                .fullMetalName(PreciousMetal.FXGLC1.getDescription())
                .price(1_000.00F)
                .recommendationAnalysts(RecommendationAnalysts.BUY.getRecommendation())
                .monthlyVolatility(15.00F)
                .build();
    }
}